#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAXSIZE 5
typedef struct Queue
{
    int data[MAXSIZE]; // 用于存储队列中元素的数值
    int front;         // 队头指针
    int rear;          // 队尾指针
} Queue, *QueuePtr;

// 初始化队列
void InitQueue(QueuePtr queue);
// 判断队列是否为空
int IsEmpty(QueuePtr queue);
// 判断队列是否已满
int IsFull(QueuePtr queue);
// 入队
int EnQueue(QueuePtr queue, int value);
// 出队
int DeQueue(QueuePtr queue, int *value);
// 获取队列的大小
int GetQueueSize(QueuePtr queue);
// 获取队头元素
int GetQueueFront(QueuePtr queue, int *value);
// 获取队尾元素
int GetQueueRear(QueuePtr queue, int *value);
// 销毁元素
int DestroyQueue(QueuePtr queue);
// 打印队列
void PrintQueue(QueuePtr queue);

int main(int argc, char const *argv[])
{
    QueuePtr q;
    // 初始化队列
    InitQueue(q);
    // 入队
    EnQueue(q, 1);
    EnQueue(q, 2);
    EnQueue(q, 3);
    EnQueue(q, 4);

    printf("队列大小为：%d\n", GetQueueSize(q));
    PrintQueue(q);

    // 出队
    int dat;
    if (!DeQueue(q, &dat))
        printf("出队：%d\n", dat);
    else
        printf("出队失败\n");
    if (!DeQueue(q, &dat))
        printf("出队：%d\n", dat);
    else
        printf("出队失败\n");

    printf("队列大小为：%d\n", GetQueueSize(q));
    PrintQueue(q);

    // 入队
    EnQueue(q, 33);
    PrintQueue(q);
    EnQueue(q, 44);
    PrintQueue(q);
    EnQueue(q, 55);
    printf("队列大小为：%d\n", GetQueueSize(q));
    PrintQueue(q);

    // 再次出队
    if (!DeQueue(q, &dat))
        printf("出队：%d\n", dat);
    else
        printf("出队失败\n");
    if (!DeQueue(q, &dat))
        printf("出队：%d\n", dat);
    else
        printf("出队失败\n");

    printf("队列大小为：%d\n", GetQueueSize(q));
    PrintQueue(q);

    //获得队头元素
    int head;
    if (!GetQueueFront(q, &head))
        printf("队头：%d\n", head);
    else
        printf("队列为空\n");

    //获得队尾元素
    int tail;
    if (!GetQueueRear(q, &tail))
        printf("队尾：%d\n", tail);
    else
        printf("队列为空\n");

    DestroyQueue(q); // 销毁
    PrintQueue(q);
    printf("队列大小为：%d\n", GetQueueSize(q));
    return 0;
}

// 初始化队列
void InitQueue(QueuePtr queue)
{
    queue->front = queue->rear = 0; // 一个空队 指向的是同一个位置 队头元素的位置
}

// 判断队列是否为空   队空:1  不空：0
int IsEmpty(QueuePtr queue)
{
    return queue->front == queue->rear;
}
// 判断队列是否已满  队满:1  不满：0
int IsFull(QueuePtr queue)
{
    if ((queue->rear + 1) % MAXSIZE == queue->front)
    {
        return 1;
    }
    return 0;
}

// 入队
int EnQueue(QueuePtr queue, int value)
{
    // 判满
    if (IsFull(queue))
    {
        printf("queue is full\n");
        return 1;
    }
    // 将数据插入 尾部
    queue->data[queue->rear] = value;
    // 更新尾部 指针/索引 的位置
    queue->rear = (queue->rear + 1) % MAXSIZE;
    return 0;
}

// 出队
int DeQueue(QueuePtr queue, int *value)
{
    // 判空
    if (IsEmpty(queue))
    {
        printf("queue is empty\n");
        return 1;
    }
    *value = queue->data[queue->front];
    queue->data[queue->front] = -1;
    // 更新队头的指针/索引
    queue->front = (queue->front + 1) % MAXSIZE;
    return 0;
}

// 获取队列的大小
int GetQueueSize(QueuePtr queue)
{
    return (queue->rear - queue->front + MAXSIZE) % MAXSIZE;
}

// 获取队头元素
int GetQueueFront(QueuePtr queue, int *value)
{
    // 判空
    if (IsEmpty(queue))
    {
        return 1;
    }
    *value = queue->data[queue->front];
    return 0;
}

// 获取队尾元素
int GetQueueRear(QueuePtr queue, int *value)
{
    if (IsEmpty(queue))
    {
        return 1;
    }
    *value = queue->data[(queue->rear - 1 + MAXSIZE) % MAXSIZE];
    return 0;
}

// 销毁元素
int DestroyQueue(QueuePtr queue)
{
    queue->front = queue->rear = 0; // 销毁
}

// 打印队列
void PrintQueue(QueuePtr queue)
{
    // 判空
    if (IsEmpty(queue))
    {
        printf("queue is empty\n");
        return;
    }
    int i;
    printf("遍历\n");
    for (i = queue->front; i != queue->rear; i = (i + 1) % MAXSIZE)
    {
        printf("%d\t", queue->data[i]);
    }
    printf("\n");
}